<?php

namespace App\Services;

use App\Exceptions\ApiException;
use App\Models\ActionLog;
use App\Models\PartCompany;
use App\Models\PhotoClassify;
use App\Models\Project;
use Illuminate\Database\Query\Builder;

/**
 * 分类目录服务层
 * Class PhotoArchivesService
 * @package App\Services
 */
class PhotoArchivesService extends BaseService
{
    public $approvalService;
    public $photoCatalogService;

    public function __construct(ApprovalService $approvalService, PhotoCatalogService $photoCatalogService)
    {
        parent::__construct();
        $this->approvalService     = $approvalService;
        $this->photoCatalogService = $photoCatalogService;
    }

    /**
     * 照片档案列表
     */
    public function getList($partCompanyId, $photoClassifyId, $perPage, $keyword, $type, $searchType)
    {
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $thisQuery = $photoArchivesInstance->where('photo_classify_id', $photoClassifyId);
        if ($type == 2) { //异常案卷
            $thisQuery->where('problem', '!=', '');
        } elseif ($type == 3) { //空案卷
            $thisQuery->where('is_have_data', '=', 0);
        } elseif ($type == 4) { //非空案卷
            $thisQuery->where('is_have_data', '=', 1);
        }
        if ($keyword) {
            $likeKeyword = "%{$keyword}%";
            if ($searchType == 2) { //文件题名
                $thisQuery->whereIn('id', function (Builder $query) use ($partCompanyId, $photoClassifyId, $likeKeyword) {
                    $table = 'photo_catalogs_' . $partCompanyId . '_' . $photoClassifyId;
                    $query->select('photo_archive_id')->from($table)->where("$table.title", 'like', $likeKeyword);
                });
            } elseif ($searchType == 3) { //档号检索
                $thisQuery->where('archives_no', 'like', $likeKeyword);
            } else { //案卷题名
                $thisQuery->where('title', 'like', $likeKeyword);
            }
        }
        $list = $thisQuery->orderBy('serial_no')->paginate($perPage);
        if ($list->isEmpty()) return [];
        $list = $list->toArray();
        foreach ($list['data'] as &$val) {
            $val['number']         = $val['serial_no'];
            $val['start_end_date'] = format_date($val['start_date'], $val['end_date']);
            $val['data_count']     = $this->getCatalogCount($partCompanyId, $photoClassifyId, $val['id']);
        }
        return $this->removeNoUsedPageParams($list);
    }

    /**
     * 批量导入照片时，单个导入
     *
     * @param $partCompanyId
     * @param $photoClassifyId
     * @param $uploadResult
     * @throws ApiException
     * @author: lxk
     * @date: 2024-09-13 14:44
     */
    public function addNewPhoto($partCompanyId, $photoClassifyId, $uploadResult)
    {
        $originName = format_archives_no($uploadResult['origin_name']);
        $pos        = strrpos($originName, '-');     //最后'-'出现的位置
        $archivesNo = substr($originName, 0, $pos);  //档案号
        $serialNo   = substr($originName, $pos + 1); //序号

        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $photoCatalogInstance  = $this->getPhotoCatalogInstance($partCompanyId, $photoClassifyId);
        $photoArchive         = $photoArchivesInstance->where('archives_no', $archivesNo)->first();
        if (empty($photoArchive)) { //如果原来的找不到档案号
            if (str_contains($archivesNo, '--')) $archivesNo = str_replace('--', '/', $archivesNo);
            $photoArchive = $photoArchivesInstance->where('archives_no', $archivesNo)->first();
            if (empty($photoArchive)) throw new ApiException('找不到照片档案，上传的照片名由档案号和照片号组成，档案号如果存在斜杠，斜杠使用双横杠 -- 代替');
        }
        $photoCatalog = $photoCatalogInstance
            ->where('photo_archive_id', $photoArchive->id)
            ->where('serial_no', $serialNo)
            ->first();
        if (empty($photoCatalog)) throw new ApiException("找不到照片号 {$serialNo}");
        $photoCatalog->file_url = 1; //标记为有照片
        $photoCatalog->save();
        //增加一条数据
        $photoCatalogImageInstance                    = $this->getPhotoCatalogImageInstance($partCompanyId, $photoClassifyId);
        $photoCatalogImageInstance->photo_archive_id = $photoArchive->id;
        $photoCatalogImageInstance->photo_catalog_id  = $photoCatalog->id;
        $photoCatalogImageInstance->file_url          = $uploadResult['file'];
        $photoCatalogImageInstance->origin_name       = $originName;
        $photoCatalogImageInstance->file_size         = $uploadResult['file_size'];
        $photoCatalogImageInstance->save();

        CommonService::addPhotoArchivesLog("批量导入档案照片：", $photoCatalogImageInstance->id, $partCompanyId, $photoClassifyId);
        CommonService::isNeedUpdatePaperCount($partCompanyId, 1); //告诉参建单位需要更新下统计
    }

    /**
     * 有的档案号包含'/'，但是文件名不可以包含斜杠，所以就使用'-'代替斜杠，
     * 把最后一个序号去掉，再把档号序号去掉，再把剩下的横杠转化为斜杠
     * @author: lxk
     * @date: 2023/6/3 17:37
     */
    public static function switchArchives($archivesNo)
    {
        if (str_contains($archivesNo, '--')) {
            $archivesNo = str_replace('--', '/', $archivesNo);
        }

        return $archivesNo;
    }

    /**
     * 获取全部的照片档案号，存到redis集合，
     */
    public function saveArchievesNoToRedis($partCompanyId, $photoClassifyId, $importCountKey)
    {
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $archivesNos           = $photoArchivesInstance->pluck('archives_no');

        if ($archivesNos->isEmpty()) return false;

        $archivesNoArr = $archivesNos->toArray();
        foreach ($archivesNoArr as $archivesNo) {
            redis()->sadd('photo_archives_no' . $importCountKey, $archivesNo);
        }
    }

    /**
     * 批量替换案卷标题或档案号
     * @author: lxk
     * @date: 2023/5/22 17:15
     */
    public function batchReplace($params)
    {
        $partCompanyId    = $params['part_company_id'];
        $photoClassifyId  = $params['photo_classify_id'];
        $selectAll        = $params['select_all']; //1全选，0非全选
        $type             = $params['type']; //1档案号，2案卷题名
        $beforeStr        = $params['before_str']; //需替换字符
        $afterStr         = $params['after_str']; //替换为
        $photoArchivesIds = to_array($params['ids']);

        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);

        $thisQuery = $photoArchivesInstance->where('photo_classify_id', $photoClassifyId);

        if (!$selectAll) $thisQuery->whereIn('id', $photoArchivesIds);

        if ($type == 1) { //替换档案号
            $thisQuery->where('archives_no', 'like', "%{$beforeStr}%")
                ->select('id', 'archives_no')
                ->orderBy('id');
        } else { //替换案卷标题
            $thisQuery->where('title', 'like', "%{$beforeStr}%")
                ->select('id', 'title')
                ->orderBy('id');
        }
        $thisQuery->chunk(50, function ($photoArchives) use ($type, $beforeStr, $afterStr) {
            foreach ($photoArchives as $photoArchive) {
                if ($type == 1) {
                    $title = str_replace($beforeStr, $afterStr, $photoArchive->archives_no);
                    $photoArchive->update(['archives_no' => $title]);
                } else {
                    $title = str_replace($beforeStr, $afterStr, $photoArchive->title);
                    $photoArchive->update(['title' => $title]);
                }
            }
        });
        $typeCon = ($type == 1) ? '照片档号' : '照片案卷题名';
        CommonService::addPhotoArchivesLog("批量替换照片案卷:{$typeCon}，将【{$beforeStr}】替换为【{$afterStr}】", 0, $partCompanyId, $photoClassifyId);

        return true;
    }

    /**
     * * 添加照片案卷
     * $needDate //这个参数是前端提交了 "start_end_date":"202209-202311", 验证合法性之后返回的 start_date: 2022-09-10 ; end_date : 2022-10-22
     * @param $params
     * @return bool
     * @throws ApiException
     * @author: lxk
     * @date: 2024/3/15 10:52
     */
    public function addNewData($params): bool
    {
        $partCompanyId         = $params['part_company_id'];
        $photoClassifyId       = $params['photo_classify_id'];
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);

        $count = to_int($params['count']); //要插入的案卷数量
        if (request()->filled('id')) { //视为插入一行，插入到被选行的上方，然后更新当前案卷下的卷内序号
            self::isAllowInsert($photoArchivesInstance, $params['id'], $count); //判断是否允许插入这么多数据
            $photoArchives = $photoArchivesInstance->where('id', $params['id'])->select('serial_no', 'archives_no')->first();
            $serialNo      = $photoArchives->serial_no;
            $content       = "插入{$count}条照片案卷";
        } else { //获取本案卷最大的序号再 + 1
            $photoArchives = $photoArchivesInstance->latest('serial_no')->select('serial_no', 'archives_no')->first();
            $serialNo      = $photoArchives ? $photoArchives->serial_no + 1 : 1;
            $content       = "添加{$count}条照片案卷";
        }
        if (empty($photoArchives)) { //一条数据也没有的情况下新增数据
            $mainArchivesNo = CommonService::getBaseArchivesNo($partCompanyId, $photoClassifyId, 2);
            $mainArchivesNo = $mainArchivesNo . 'XXX';
        } else {
            $archivesPart   = CommonService::getArchivesPart($photoArchives->archives_no);
            $mainArchivesNo = $archivesPart['main'];
        }
        $batchData = [];
        for ($i = 0; $i < $count; $i++) {
            if (request()->filled('id')) { //插入数据，序号递减
                $newSerialNo = $serialNo - $i - 1;
            } else { //新增数据，数据递增
                $newSerialNo = $serialNo + $i;
            }
            $newArchivesNo                      = $mainArchivesNo . '-' . $newSerialNo;
            $batchData[$i]['company_id']        = company_id();
            $batchData[$i]['part_company_id']   = $partCompanyId;
            $batchData[$i]['photo_classify_id'] = $photoClassifyId;
            $batchData[$i]['serial_no']         = $newSerialNo;
            $batchData[$i]['archives_no']       = $newArchivesNo;
            $batchData[$i]['title']             = '这是案卷标题';
            $batchData[$i]['store_period']      = '永久';
            $batchData[$i]['creator_id']        = user_id();
            $batchData[$i]['created_at']        = now();
            $batchData[$i]['updated_at']        = now();
        }
        $photoArchivesInstance->insert($batchData);

        CommonService::addPhotoArchivesLog($content, $photoArchivesInstance->id, $partCompanyId, $photoClassifyId);

        return true;
    }

    /**
     * 更新一条数据
     * 这里使用 ORM更新方式，是因为这样可以进行时间监听，记录变化
     */
    public function updateData($id, $params)
    {
        $partCompanyId         = $params['part_company_id'];
        $photoClassifyId       = $params['photo_classify_id'];
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);

        $photoArchives = $photoArchivesInstance->find($params['id']);

        $photoArchives->title         = $params['title'];
        $photoArchives->serial_no     = to_int($params['serial_no']);
        $photoArchives->archives_no   = format_archives_no($params['archives_no']);
        $photoArchives->store_period  = $params['store_period'];
        $photoArchives->page_num      = $params['page_num'];
        $photoArchives->start_date    = $params['start_date'] ?? '';
        $photoArchives->end_date      = $params['end_date'] ?? '';
        $photoArchives->remark        = $params['remark'] ?? '';
        $photoArchives->creator_id    = user_id();
        $photoArchives->is_need_check = 1; //如果案卷进行了修改，要重新检查

        CommonService::addProjectActionLog('修改照片档案', $id, $partCompanyId, $photoClassifyId);

        return $photoArchives->save();
    }

    /**
     * 判断当前用户是否可以操作案卷和卷内
     * 如果用户所在项目的参见单位和当前参见单位不一致，return 0;
     */
    public static function isAllowOperate($partCompanyId)
    {
        $projectId = PartCompany::query()->where('id', $partCompanyId)->value('project_id');

        $result = ProjectService::partCompanyUser($projectId);

        if (!$result || ($partCompanyId != $result['part_company_id'])) {
            return 0;
        }

        return 1;
    }

    /**
     * 验证输入的案卷数量是否合法
     */
    public static function checkCount($count, $maxCount = 100)
    {
        if (empty($count)) {
            return false;
        } elseif (!is_numeric($count)) {
            return false;
        } elseif ($count < 1 || $count > $maxCount) {
            return false;
        } else {
            return true;
        }
    }

    /**
     * 判断是否允许插入
     */
    public static function isAllowInsert($photoArchivesInstance, $id, $count)
    {
        $info = $photoArchivesInstance->where('id', $id)->select('serial_no', 'archives_no')->first(); //选中的案卷

        $preSerialNo = $photoArchivesInstance->where('serial_no', '<', $info->serial_no)->max('serial_no'); //上一条数据序号
        $nowSerianNo = $info->serial_no;
        $maxCount    = $nowSerianNo - $preSerialNo - 1; //最多可插入数量
        if ($maxCount == 0) {
            throw new ApiException('序号是连续的，没有插入新数据的位置');
        }
        if ($count > $maxCount) { //意思是如果两个序号之间最多容乃 5 条，比如 4和10之间，你要插入30条，肯定不合法的
            throw new ApiException("最多只能插入【{$maxCount}】条案卷");
        }
        return true;
    }

    /**
     * 照片档案详情
     * $type //点击的类型：1第一卷, 2上一卷, 3下一卷, 4最后卷
     * $currentId //当前案卷目录id
     * @author: lxk
     * @date: 2023/6/2 14:43
     */
    public function detail($partCompanyId, $photoClassifyId, $currentId, $type)
    {
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $info = $photoArchivesInstance->where('id', '=', $currentId)->first();
        $archivesNoInfo = self::getSerialNos($photoArchivesInstance, $info->archives_no);
        $main           = $archivesNoInfo['main'];
        $minSerialNo    = $archivesNoInfo['min'];
        $maxSerialNo    = $archivesNoInfo['max'];
        switch ($type) {
            case 1: //第一卷
                $info = $photoArchivesInstance->oldest('serial_no')->first();
                break;
            case 2: //上一卷
                $preSerialNo = $photoArchivesInstance->where('serial_no', '<', $info->serial_no)->max('serial_no'); //上一条数据 id
                $info        = $photoArchivesInstance->where('serial_no', $preSerialNo)->first();
                break;
            case 3: //下一卷
                $nextSerialNo = $photoArchivesInstance->where('serial_no', '>', $info->serial_no)->min('serial_no'); //下一条数据 id
                $info         = $photoArchivesInstance->where('serial_no', $nextSerialNo)->first();
                break;
            case 4: //最后卷
                $info = $photoArchivesInstance->latest('serial_no')->first();
                break;
        }
        if (empty($info)) { //如果数据不存在，返回当前数据
            $info = $photoArchivesInstance->oldest('id')->first();
        }
        $info->main_archive   = $main;
        $info->first_archive  = $main . '-' . $minSerialNo;
        $info->end_archive    = $main . '-' . $maxSerialNo;
        $catalogCount         = $this->getCatalogCount($partCompanyId, $photoClassifyId, $currentId);
        $maxPageNum           = $this->getMaxPageNum($partCompanyId, $photoClassifyId, $currentId);
        $info->append_remark  = "共 {$catalogCount} 件，{$maxPageNum} 页";
        $info->start_end_date = format_date($info->start_date, $info->end_date);

        return $info->toArray();
    }

    /**
     * @param $photoArchivesInstance
     * @param $archivesNo
     * @return array
     * @author: lxk
     */
    public static function getSerialNos($photoArchivesInstance, $archivesNo): array
    {
        $archivesNoInfo = CommonService::getArchivesPart($archivesNo);
        $main           = $archivesNoInfo['main'];
        if ($res = redis()->get($main)) {
            return json_decode($res, true);
        }
        $archivesNos = $photoArchivesInstance->where('archives_no', 'like', "{$main}%")->pluck('archives_no');
        $serialNoArr = [];
        foreach ($archivesNos as $archivesNo) {
            $archivesNoInfo = CommonService::getArchivesPart($archivesNo);
            $serialNoArr[]  = $archivesNoInfo['ext'];
        }
        $res = [
            'main' => $main,
            'min'  => min($serialNoArr),
            'max'  => max($serialNoArr)
        ];
        redis()->setex($main, 120, json_encode($res));

        return $res;
    }

    /**
     * 获取一个照片案卷的卷内最大页码
     */
    public function getMaxPageNum($partCompanyId, $photoClassifyId, $photoArchivesId)
    {
        $photoCatalogInstance = $this->getPhotoCatalogInstance($partCompanyId, $photoClassifyId);
        $info = $photoCatalogInstance //序号倒序获取第一条数据
        ->where('photo_archives_id', $photoArchivesId)
            ->orderByDesc('serial_no')
            ->first();

        if (empty($info)) return 0;

        $pageNum = $info->page_num;
        if (is_numeric($pageNum)) return $pageNum;

        $pos    = strrpos($pageNum, '～');
        $result = json_encode(mb_substr($pageNum, $pos + 1));
        if (!empty($result)) {
            $maxPageNum = mb_substr($pageNum, $pos + 1);
        } else {
            $maxPageNum = mb_substr($pageNum, $pos + 3);
        }
        return $maxPageNum;
    }

    /**
     * 获取一个案卷的卷内数量
     */
    public function getCatalogCount($partCompanyId, $photoClassifyId, $photoArchivesId)
    {
        $photoCatalogInstance = $this->getPhotoCatalogInstance($partCompanyId, $photoClassifyId);

        return $photoCatalogInstance->where('photo_archives_id', $photoArchivesId)->count('id') ?: 0;
    }

    /**
     * 获取 项目名、参建单位名、项目分类名
     */
    public static function getProjectContent($partCompanyId, $photoClassifyId)
    {
        $partCompany  = PartCompany::query()->find($partCompanyId);
        $projectName  = Project::query()->where('id', $partCompany->project_id)->value('title');
        $classifyName = PhotoClassify::query()->where('id', $photoClassifyId)->value('title');
        return [
            'project'        => $projectName,
            'part_company'   => $partCompany->title,
            'photo_classify' => $classifyName,
        ];
    }

    /**
     * 添加操作日志（普通）
     */
    public static function addActionLog($event, $detail = '')
    {
        $adminLog = new ActionLog();

        $adminLog->user_id      = user_id();
        $adminLog->company_id   = company_id();
        $adminLog->user_name    = user()->nickname;
        $adminLog->company_name = company_name();
        $adminLog->role_name    = role_name();
        $adminLog->event        = $event;
        $adminLog->detail       = $detail;
        $adminLog->action_ip    = request()->ip();

        $adminLog->save();
    }

    /**
     * 限制用户1分钟内不得重复点击【检查案卷】
     */
    public function limitClickCount($photoClassifyId)
    {
        redis()->setex('click_count' . $photoClassifyId, 60, $photoClassifyId);
    }

    /**
     * 检查数据合法性
     * 如果某个案卷检查完毕，那就把这个案卷的起止日期和页次更新进来
     * @author: lxk
     * @date: 2023/5/22 16:54
     */
    public function checkData($partCompanyId, $photoClassifyId, $selectIds)
    {
        $photoArchiveInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $photoArchivesIds     = $photoArchiveInstance->where('photo_classify_id', $photoClassifyId)->pluck('id');
        if ($photoArchivesIds->isEmpty()) throw new ApiException('暂无案卷！');

        $photoArchiveInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $photoCatalogInstance = $this->getPhotoCatalogInstance($partCompanyId, $photoClassifyId);

        $bookTitleIds = $photoArchiveInstance->where('photo_classify_id', $photoClassifyId)->pluck('id');
        if ($bookTitleIds->isEmpty()) throw new ApiException('暂无案卷！');

        $redisKey      = get_rand_str('photo_archives'); //使用集合存放标题
        $selectIds     = to_array($selectIds); //如果选择了照片档案
        $checkCountKey = get_rand_str('photo_check_count'); //检查了几条案卷
        redis()->set($checkCountKey, 0);

        $photoArchiveInstance //第一步，先检查案卷数据
        ->where('is_need_check', 1) //检查结束后不需要检查的会标记为0
        ->when($selectIds, function ($query) use ($selectIds) {
            $query->whereIn('id', $selectIds);
        })
            ->select('id', 'serial_no', 'archives_no', 'title', 'page_num', 'start_date', 'end_date')
            ->orderBy('id') //注意，既然chunkById()了，这里必须用id排序，否则如果id从小到大之后但是serial_no不是从小到大，就会进入死循环报错
            ->chunkById(100, function ($list) use ($photoArchiveInstance, $photoCatalogInstance, $redisKey, $checkCountKey) {
                foreach ($list as $val) {
                    $id = to_array($val['id']);
                    $this->photoCatalogService->checkPhotoCatalogData($photoArchiveInstance, $photoCatalogInstance, $val['id']);
                    if (!redis()->sadd($redisKey, $val['title'])) { //如果加入失败，说明标题重复
                        self::problemMark($photoArchiveInstance, $id, '案卷题名重复!请复制名称搜索');
                    }
                    $photoArchiveInstance->where('id', $val['id'])->update(['is_need_check' => 0]);
                    redis()->incrby($checkCountKey, 1);
                }
            });
        $checkCount = redis()->get($checkCountKey);
        redis()->del($redisKey); //redis临时变量用完清除
        redis()->del($checkCountKey);

        $errorCount = $photoArchiveInstance->where('problem', '!=', '')->count('id');
        $emptyCount = $photoArchiveInstance->where('is_have_data', 0)->count('id');
        if (!empty($selectIds)) {
            $selectCount = count($selectIds);
            $msg         = "检查了勾选的【{$selectCount}】个案卷";
        } else {
            $msg = $checkCount ? "本次检查了【{$checkCount}】个案卷" : "本次没有案卷需要检查";
        }
        $msg = $msg . "；当前共有【{$emptyCount}个空案卷】";

        return ($errorCount > 0) ? $msg . ",【{$errorCount}个异常案卷】" : $msg . "，【0个异常案卷】";
    }

    /**
     * 检查数据合法性
     * 如果某个案卷检查完毕，那就把这个案卷的起止日期和页次更新进来
     * @author: lxk
     * @date: 2023/5/22 16:54
     */
    public function checkData2($partCompanyId, $projectClassifyId, $selectIds, $problemBookTitleIds)
    {
        $bookTitleInstance   = $this->getBookTitleInstance($partCompanyId, $projectClassifyId);
        $bookCatalogInstance = $this->getBookCatalogInstance($partCompanyId, $projectClassifyId);

        $bookTitleIds = $bookTitleInstance->where('project_classify_id', $projectClassifyId)->pluck('id');

        if ($bookTitleIds->isEmpty()) throw new ApiException('暂无案卷！');

        $combinationId = (new ProjectService())->getDossierCombination($partCompanyId, $projectClassifyId);

        $redisKey  = get_rand_str('book_title'); //使用集合存放标题
        $selectIds = to_array($selectIds); //如果选择了案卷

        $checkCountKey = get_rand_str('check_count'); //检查了几条案卷
        redis()->set($checkCountKey, 0);

        $bookTitleInstance //第一步，先检查案卷数据。（1）如果指定案卷，只检查指定案卷
        ->when($selectIds, function ($query) use ($selectIds) {
            $query->whereIn('id', $selectIds);
        }, function ($query) use ($problemBookTitleIds) {
            if ($problemBookTitleIds->isNotEmpty()) {
                $problemBookTitleIds = $problemBookTitleIds->toArray();
                $query->whereIn('id', $problemBookTitleIds); //（2）如果没指定案卷，但存在异常案卷，检查异常案卷
            } else {
                $query->where('id', '>', 0);
            }
        })
            ->select('id', 'serial_no', 'archives_no', 'title', 'page_num', 'blueprint', 'word_material', 'start_date', 'end_date', 'problem')
            ->orderBy('id') //注意，既然chunkById()了，这里必须用id排序，否则如果id从小到大之后但是serial_no不是从小到大，就会进入死循环报错
            ->chunkById(100, function ($list) use ($bookTitleInstance, $bookCatalogInstance, $combinationId, $redisKey, $checkCountKey) {
                foreach ($list as $val) {
                    $id = to_array($val['id']);
                    //页次的值不等于蓝图和文字材料相加..逻辑待定
                    $this->bookCatalogService->checkBookCatalogData($bookTitleInstance, $bookCatalogInstance, $val['id'], $combinationId);
                    if (!redis()->sadd($redisKey, $val['title'])) { //如果加入失败，说明标题重复
                        self::problemMark($bookTitleInstance, $id, '案卷题名重复!请复制名称搜索');
                    }
                    redis()->incrby($checkCountKey, 1);
                }
            });

        $checkCount = redis()->get($checkCountKey);
        redis()->del($redisKey); //用完清除
        redis()->del($checkCountKey);

        if (!empty($selectIds)) {
            $selectCount = count($selectIds);
            $msg         = "检查并更新了勾选的【{$selectCount}】个案卷";
        } elseif ($problemBookTitleIds->isNotEmpty()) {
            $msg = "优先检查并更新了【{$checkCount}】个异常案卷";
        } else {
            $msg = "检查并更新了该单位工程下的全部案卷";
        }
        $errorCount = $bookTitleInstance->where('problem', '!=', '')->count('id');

        return ($errorCount > 0) ? $msg . '；当前共存在【' . $errorCount . '】个异常案卷' : "检查完毕！未发现异常";
    }

    /**
     * 案卷问题标记
     */
    public static function problemMark($bookTitleInstance, $ids, $problem)
    {
        return $bookTitleInstance->whereIn('id', $ids)->update(['problem' => $problem]);
    }

    /**
     * 移除问题标记，如果卷内有问题，所属案卷也进行标记
     */
    public static function removeMark($bookCatalogInstance, $bookCatalogId, $bookTitleInstance, $bookTitleId)
    {
        $bookTitleInstance->where('id', $bookTitleId)->update(['problem' => '']);
        $bookCatalogInstance->where('id', $bookCatalogId)->update(['problem' => '']);
    }

    /**
     * 删除若干数据后，剩余的数据序号和档案号重新排列，第一个序号为1 从小到大递增
     */
    public function delData($partCompanyId, $photoClassifyId, $ids)
    {
        $photoArchivesInstance = $this->getPhotoArchiveInstance($partCompanyId, $photoClassifyId);
        $archivesNo            = $photoArchivesInstance->where('id', $ids[0])->value('archives_no');//当前档案号
        $mainArchivesNo        = substr($archivesNo, 0, strrpos($archivesNo, '-')); //获取主档案号

        $delSerialNos = $photoArchivesInstance //删除了哪些序号
        ->whereIn('id', $ids)
            ->orderBy('serial_no')
            ->pluck('serial_no')
            ->toArray();

        if (!$photoArchivesInstance->whereIn('id', $ids)->delete()) {
            throw new ApiException('删除失败！');
        };
        $photoArchivesInstance
            ->where('part_company_id', $partCompanyId)
            ->where('photo_classify_id', $photoClassifyId)
            ->select('id', 'serial_no', 'archives_no')
            ->orderBy('serial_no', 'asc')
            ->chunk(100, function ($list) use ($mainArchivesNo, $delSerialNos) {
                $minSerialNo = min($delSerialNos);
                foreach ($list as $bookTitle) {
                    if ($bookTitle->serial_no < $minSerialNo) {
                        $serialNo = $bookTitle->serial_no;
                    } else {
                        $serialNo = $this->getNewSerialNo($bookTitle->serial_no, $delSerialNos); //变化后的值
                    }
                    $bookTitle->update(['serial_no' => $serialNo, 'archives_no' => $mainArchivesNo . '-' . $serialNo]);
                }
            });
        $ids = implode(',', $ids);
        CommonService::addPhotoArchivesLog("删除照片案卷", $ids, $partCompanyId, $photoClassifyId);

        return true;
    }


}
